#     Copyright 2024. ThingsBoard
#
#     Licensed under the Apache License, Version 2.0 (the "License");
#     you may not use this file except in compliance with the License.
#     You may obtain a copy of the License at
#
#         http://www.apache.org/licenses/LICENSE-2.0
#
#     Unless required by applicable law or agreed to in writing, software
#     distributed under the License is distributed on an "AS IS" BASIS,
#     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#     See the License for the specific language governing permissions and
#     limitations under the License.

import time
import struct
from crcmod import mkCrcFun
from binascii import unhexlify

from simplejson import dumps

from thingsboard_gateway.connectors.mqtt.mqtt_uplink_converter import MqttUplinkConverter


class CustomMqttUplinkConverter(MqttUplinkConverter):
    def __init__(self, config, logger):
        self._log = logger
        self.__config = config.get('converter')

    @property
    def config(self):
        return self.__config

    def convert(self, topic, body):
        try:
            dict_result = {
                "deviceName": "Demo Device1",
                "deviceType": "default",
                "attributes": [],
                "telemetry": []
                # "telemetry": [{"ts": int(time.time()) * 1000, 'values': {"humidity": 70}}]
            }
            recv_bytes = bytes.fromhex(body)
            recv_bytes_len = len(recv_bytes)
            if self.recv_check(recv_bytes, recv_bytes_len):
                data_len = int(self.reverse_byte_order(bytearray(recv_bytes)[4:6].hex()),16)
                device_id = int(self.reverse_byte_order(bytearray(recv_bytes)[6:8].hex()),16)
                sampling_points = int(bytearray(recv_bytes)[8:9].hex(),16)
                sampling_frequency = int(bytearray(recv_bytes)[9:10].hex(),16)
                # 检验数据长度
                if data_len!=2+1+1+4*sampling_points*sampling_frequency:
                    self._log.info("data_len error")
                dict_result["attributes"].append({"device_id":device_id})
                dict_result["attributes"].append({"sampling_points":sampling_points})
                dict_result["attributes"].append({"sampling_frequency":sampling_frequency})
                for i in range(sampling_points):
                    values=[]
                    for j in range(sampling_frequency):
                        begin = 10+j*4*sampling_points+i*4
                        end = 4+begin
                        sampling_value = self.hex_to_float(self.reverse_byte_order(bytearray(recv_bytes)[begin:end].hex()))
                        timestamp = int(time.time())
                        # values.append({"sampling_frequency_{:02}".format(j): sampling_value,
                        #                "timestamp":timestamp*1000+j*int((1000/sampling_frequency))})
                        values.append([timestamp*1000+j*int((1000/sampling_frequency)),sampling_value])
                    dict_result["telemetry"].append({"ts":  timestamp * 1000, 'values': {"sampling_points_{:02}".format(i+1): values}})
                    # dict_result["telemetry"].append({"ts":  timestamp * 1000, 'values': {"sampling_points_{:02}".format(i+1): sampling_value}})
                # print((j+i*sampling_frequency)*(1000/sampling_points*sampling_frequency))
            else:
                self._log.info("check error")
            return dict_result

        except Exception as e:
            self._log.exception('Error in converter, for config: \n%s\n and message: \n%s\n', dumps(self.__config), body)
            self._log.exception(e)

    def reverse_byte_order(self, hex_string):
        # 将十六进制字符串转换为字节序列
        byte_seq = bytes.fromhex(hex_string)
        # 反转字节序列的字节顺序
        reversed_byte_seq = bytearray(reversed(byte_seq))
        # 将反转后的字节序列转换回十六进制字符串
        reversed_hex_string = reversed_byte_seq.hex().upper()
        return reversed_hex_string
    
    def hex_to_float(self, hex_str):
        # 将16进制字符串转换为4字节的字节序列
        hex_bytes = bytes.fromhex(hex_str)
        # 使用unpack从字节序列中解包出float
        return struct.unpack('!f', hex_bytes)[0]
    
    def recv_check(self, recv_bytes, recv_bytes_len):
        recv_head = bytearray(recv_bytes)[0:4].hex().upper()
        recv_end = bytearray(recv_bytes)[recv_bytes_len-1:recv_bytes_len].hex().upper()
        recv_crc = bytearray(recv_bytes)[recv_bytes_len-3:recv_bytes_len-1].hex().upper()
        recv_data = bytearray(recv_bytes)[4:recv_bytes_len-3].hex().upper()
        crc = self.crc16_modbus(recv_data)
        # print("crc:"+crc)
        return False if recv_head!="6D6D2022" or recv_end!="96" or crc!=recv_crc else True

    def crc16_modbus(self, s):
        crc16 = mkCrcFun(0x18005, rev=True, initCrc=0xFFFF, xorOut=0x0000)
        data = s.replace(' ', '')
        crc_out = hex(crc16(unhexlify(data))).upper()
        str_list = list(crc_out)
        if len(str_list) == 5:
            str_list.insert(2, '0')  # 位数不足补0
        crc_data = ''.join(str_list[2:])
        return crc_data[2:] + crc_data[:2]

